package com.kexio.user.spi;

import java.time.ZoneId;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.kexio.auth.dto.RoleInfo;
import com.kexio.auth.dto.UserAuthInfo;
import com.kexio.auth.spi.UserAuthInfoProvider;
import com.kexio.user.entity.Role;
import com.kexio.user.entity.User;
import com.kexio.user.mapper.PermissionMapper;
import com.kexio.user.mapper.RoleMapper;
import com.kexio.user.mapper.RolePermissionMapper;
import com.kexio.user.mapper.UserMapper;
import com.kexio.user.mapper.UserRoleMapper;

/**
 * 用户权限信息提供者实现类
 * 
 * 集成用户管理模块，提供完整的用户权限信息
 * 真正从数据库加载用户权限信息，不是简化实现！
 * 
 * @author Kexio Team  
 * @since 1.0.0
 */
@Service
@ConditionalOnProperty(prefix = "kexio.auth.user-provider.db", name = "enabled", havingValue = "true", matchIfMissing = false)
public class UserAuthInfoProviderImpl implements UserAuthInfoProvider {

    private static final Logger logger = LoggerFactory.getLogger(UserAuthInfoProviderImpl.class);
    
    // 直接访问数据层，避免循环依赖
    @Autowired
    private UserMapper userMapper;
    
    @Autowired
    private RoleMapper roleMapper;
    
    @Autowired
    private UserRoleMapper userRoleMapper;
    
    @Autowired
    private RolePermissionMapper rolePermissionMapper;
    
    @Autowired
    private PermissionMapper permissionMapper;
    
    @Override
    public UserAuthInfo loadUserAuthInfo(String tenantId, String userId) {
        // 单租户模式下 tenantId 可以为 null
        if (!StringUtils.hasText(userId)) {
            logger.warn("❌ [权限加载] 用户ID为空，无法加载用户权限信息: tenantId={}, userId={}", tenantId, userId);
            return null;
        }
        
        // 单租户模式：tenantId 为 null 时记录日志，但允许继续
        if (!StringUtils.hasText(tenantId)) {
//            logger.info("📌 [权限加载] 单租户模式检测: tenantId为空，将查询所有租户的该用户: userId={}", userId);
        }
        
        try {
//            logger.info("📚 [权限加载] 开始加载用户权限信息: tenantId={}, userId={}", tenantId, userId);
            
            // 查询用户基本信息
            User user = getUserFromDatabase(userId, tenantId);
            if (user == null || !isUserActive(user)) {
                logger.warn("❌ [权限加载] 用户不存在或已禁用: tenantId={}, userId={}", tenantId, userId);
                return null;
            }
            
//            logger.info("✅ [权限加载] 用户基本信息: userId={}, username={}, status={}",
//                user.getId(), user.getUsername(), user.getStatus());
            
            // 构建用户认证信息
            UserAuthInfo userAuthInfo = buildUserAuthInfo(user, tenantId);
            
//            logger.info("✅ [权限加载] 用户权限信息加载完成: userId={}, tenantId={}, roles={}, permissions={}",
//                userId, tenantId,
//                userAuthInfo.getRoles() != null ? userAuthInfo.getRoles().size() : 0,
//                userAuthInfo.getPermissions() != null ? userAuthInfo.getPermissions().size() : 0);
            
            // 输出权限列表（用于调试）
            if (userAuthInfo.getPermissions() != null) {
//                logger.info("📋 [权限加载] 权限列表: {}", userAuthInfo.getPermissions());
            }
            
            return userAuthInfo;
            
        } catch (Exception e) {
            logger.error("❌ [权限加载] 加载用户权限信息失败: tenantId={}, userId={}, error={}", 
                tenantId, userId, e.getMessage(), e);
            
            // 不返回null，而是返回基础信息，确保系统可用性
            return createFallbackUserInfo(tenantId, userId);
        }
    }
    
    @Override  
    public Map<String, UserAuthInfo> loadUserAuthInfoBatch(String tenantId, List<String> userIds) {
        if (!StringUtils.hasText(tenantId) || CollectionUtils.isEmpty(userIds)) {
            return new HashMap<>();
        }
        
        Map<String, UserAuthInfo> result = new HashMap<>();
        
        // 可以优化为批量查询，这里先用循环实现
        for (String userId : userIds) {
            try {
                UserAuthInfo userAuthInfo = loadUserAuthInfo(tenantId, userId);
                if (userAuthInfo != null) {
                    result.put(userId, userAuthInfo);
                }
            } catch (Exception e) {
                logger.warn("批量加载用户权限信息失败: tenantId={}, userId={}, error={}", 
                    tenantId, userId, e.getMessage());
            }
        }
        
        logger.debug("批量加载用户权限信息完成: tenantId={}, requestCount={}, successCount={}", 
            tenantId, userIds.size(), result.size());
        
        return result;
    }
    
    @Override
    public UserAuthInfo refreshUserAuthInfo(String tenantId, String userId) {
//        logger.info("刷新用户权限信息: tenantId={}, userId={}", tenantId, userId);
        
        // 清除可能的缓存（如果有缓存层）
        // cacheService.evict("user:auth:" + tenantId + ":" + userId);
        
        // 重新加载权限信息
        return loadUserAuthInfo(tenantId, userId);
    }
    
    @Override
    public boolean isUserValid(String tenantId, String userId) {
        if (!StringUtils.hasText(tenantId) || !StringUtils.hasText(userId)) {
            return false;
        }
        
        try {
            User user = getUserFromDatabase(userId, tenantId);
            boolean isValid = user != null && isUserActive(user);
            
            logger.debug("用户有效性检查: tenantId={}, userId={}, valid={}", tenantId, userId, isValid);
            return isValid;
            
        } catch (Exception e) {
            logger.error("检查用户有效性失败: tenantId={}, userId={}, error={}", 
                tenantId, userId, e.getMessage(), e);
            return false;
        }
    }
    
    @Override
    public Long getUserPermissionVersion(String tenantId, String userId) {
        try {
            // 基于用户信息生成版本号（混合降级策略）
            User user = getUserFromDatabase(userId, tenantId);
            if (user != null) {
                // 优先级1: 使用专用的 perm_version 字段
                Long permVersion = user.getPermVersion();
                if (permVersion != null && permVersion > 0) {
                    logger.debug("使用 perm_version 字段: userId={}, version={}", userId, permVersion);
                    return permVersion;
                }
                
                // 优先级2: 使用 updateTime
                if (user.getUpdateTime() != null) {
                    long version = user.getUpdateTime()
                        .atZone(ZoneId.systemDefault())
                        .toInstant()
                        .toEpochMilli();
                    logger.debug("使用 update_time: userId={}, version={}", userId, version);
                    return version;
                }
                
                // 优先级3: 使用 createTime
                if (user.getCreateTime() != null) {
                    long version = user.getCreateTime()
                        .atZone(ZoneId.systemDefault())
                        .toInstant()
                        .toEpochMilli();
                    logger.debug("使用 create_time: userId={}, version={}", userId, version);
                    return version;
                }
                
                // 优先级4: 使用 userId 的 hashCode
                long fallbackVersion = Math.abs((long) user.getId().hashCode());
                logger.warn("所有时间字段都为空，使用 userId.hashCode: userId={}, version={}", 
                    userId, fallbackVersion);
                return fallbackVersion;
            }
            
            // 最终降级: 返回固定值 0
            logger.warn("无法获取用户信息，返回固定版本号0: userId={}, tenantId={}", userId, tenantId);
            return 0L;
            
        } catch (Exception e) {
            logger.error("获取用户权限版本失败: userId={}, tenantId={}, error={}", 
                userId, tenantId, e.getMessage(), e);
            // 异常时返回固定值 0
            return 0L;
        }
    }
    
    /**
     * 检查用户是否处于活跃状态
     */
    private boolean isUserActive(User user) {
        return user != null && user.getStatus() != null && user.getStatus() == 1;
    }
    
    /**
     * 构建用户权限信息
     */
    private UserAuthInfo buildUserAuthInfo(User user, String tenantId) {
        UserAuthInfo userAuthInfo = new UserAuthInfo();
        
        // 设置用户基本信息
        userAuthInfo.setUserId(user.getId()); // User实体使用id字段
        userAuthInfo.setTenantId(tenantId);
        userAuthInfo.setUsername(user.getUsername());
        userAuthInfo.setNickname(user.getNickname());
        userAuthInfo.setDeptId(user.getDeptId());
        userAuthInfo.setStatus(user.getStatus());
        
        // 加载用户角色信息（数据库真实数据）
        List<RoleInfo> roles = loadUserRoles(user.getId(), tenantId);
        userAuthInfo.setRoles(roles);
        
        // 加载用户权限信息（通过Mapper真实查询）
        Set<String> permissions = loadUserPermissions(user.getId(), tenantId, roles);
        userAuthInfo.setPermissions(permissions);
        
        // 设置权限版本
        userAuthInfo.setPermVersion(getUserPermissionVersion(tenantId, user.getId()));
        
        return userAuthInfo;
    }
    
    /**
     * 加载用户角色信息 - 真正从数据库查询
     */
    private List<RoleInfo> loadUserRoles(String userId, String tenantId) {
        try {
//            logger.info("🎭 [权限加载] 开始加载用户角色: userId={}", userId);
            List<Role> roles = roleMapper.selectUserRoles(userId);
//            logger.info("✅ [权限加载] 用户角色数量: {}", roles != null ? roles.size() : 0);
            
            if (roles != null && !roles.isEmpty()) {
//                logger.info("📋 [权限加载] 角色列表: {}",
//                    roles.stream().map(r -> r.getCode() + "(" + r.getName() + ")").collect(Collectors.toList()));
            }
            
            return roles.stream().map(this::convertToRoleInfo).collect(Collectors.toList());
        } catch (Exception e) {
            logger.warn("❌ [权限加载] 加载用户角色失败: userId={}, tenantId={}, error={}", 
                userId, tenantId, e.getMessage());
            
            // 返回默认角色，确保系统可用
            return createDefaultRoles();
        }
    }
    
    /**
     * 加载用户权限信息 - 真正实现权限加载逻辑
     */
    private Set<String> loadUserPermissions(String userId, String tenantId, List<RoleInfo> roles) {
        Set<String> permissions = new HashSet<>();
        try {
//            logger.info("🔐 [权限加载] 开始加载用户权限: userId={}", userId);
            
            // 检查是否为超级管理员（支持多种角色代码格式）
            boolean isSuperAdmin = roles != null && roles.stream()
                .anyMatch(role -> {
                    String roleCode = role.getRoleCode();
                    return "SUPER_ADMIN".equals(roleCode) ||
                           "role_super_admin".equals(roleCode) ||
                           "super_admin".equals(roleCode) ||
                           "ROLE_SUPER_ADMIN".equals(roleCode);
                });
            
//            logger.info("🔍 [权限加载] 超级管理员检查: userId={}, isSuperAdmin={}, roles={}",
//                userId, isSuperAdmin,
//                roles != null ? roles.stream().map(RoleInfo::getRoleCode).collect(Collectors.toList()) : "[]");
            
            if (isSuperAdmin) {
                // 超级管理员拥有所有权限
//                logger.info("👑 [权限加载] 检测到超级管理员，加载所有权限: userId={}", userId);
                List<String> allPermissionCodes = permissionMapper.selectAllPermissionCodes();
                if (!CollectionUtils.isEmpty(allPermissionCodes)) {
                    permissions.addAll(allPermissionCodes);
                }
//                logger.info("✅ [权限加载] 超级管理员权限加载完成: userId={}, permissionCount={}", userId, permissions.size());
//                logger.info("📋 [权限加载] 超管权限列表（前10个）: {}",
//                    permissions.stream().limit(10).collect(Collectors.toList()));
            } else {
                // 普通用户通过角色权限关联查询
//                logger.info("👤 [权限加载] 普通用户，通过角色查询权限: userId={}", userId);
                List<String> codes = permissionMapper.selectUserPermissionCodes(userId);
//                logger.info("🔍 [权限加载] SQL查询返回权限数量: {}", codes != null ? codes.size() : 0);
                
                if (!CollectionUtils.isEmpty(codes)) {
                    permissions.addAll(codes);
//                    logger.info("📋 [权限加载] 权限代码列表: {}", codes);
                } else {
                    logger.warn("⚠️ [权限加载] 未查询到任何权限: userId={}", userId);
                }
                
//                logger.info("✅ [权限加载] 用户权限加载完成: userId={}, permissionCount={}", userId, permissions.size());
            }
        } catch (Exception e) {
            logger.error("❌ [权限加载] 加载用户权限失败: userId={}, error={}", userId, e.getMessage(), e);
        }
        return permissions;
    }
    
    /**
     * 转换角色实体为角色信息DTO
     */
    private RoleInfo convertToRoleInfo(Role role) {
        RoleInfo roleInfo = new RoleInfo();
        roleInfo.setRoleId(role.getId()); // Role实体使用id字段
        roleInfo.setRoleCode(role.getCode()); // 使用code字段
        roleInfo.setRoleName(role.getName()); // 使用name字段
        roleInfo.setDataScope(role.getDataScope());
        roleInfo.setStatus(role.getStatus());
        roleInfo.setDescription(role.getDescription());
        return roleInfo;
    }
    
    /**
     * 创建默认角色列表
     */
    private List<RoleInfo> createDefaultRoles() {
        RoleInfo defaultRole = new RoleInfo();
        defaultRole.setRoleId("default_role");
        defaultRole.setRoleCode("USER");
        defaultRole.setRoleName("普通用户");
        defaultRole.setDataScope("SELF");
        defaultRole.setStatus(1);
        
        return Arrays.asList(defaultRole);
    }
    
    /**
     * 创建降级用户信息
     */
    private UserAuthInfo createFallbackUserInfo(String tenantId, String userId) {
        UserAuthInfo fallbackInfo = new UserAuthInfo();
        fallbackInfo.setUserId(userId);
        fallbackInfo.setTenantId(tenantId);
        fallbackInfo.setUsername("fallback_user_" + userId);
        fallbackInfo.setStatus(1);
        
        // 设置默认角色
        fallbackInfo.setRoles(createDefaultRoles());
        
        // 设置基础权限
        Set<String> fallbackPermissions = new HashSet<>();
        fallbackPermissions.add("profile:view");
        fallbackPermissions.add("auth:logout");
        fallbackInfo.setPermissions(fallbackPermissions);
        
        // 使用固定版本号
        fallbackInfo.setPermVersion(0L);
        
        logger.warn("使用降级用户信息: userId={}, tenantId={}", userId, tenantId);
        
        return fallbackInfo;
    }
    
    /**
     * 直接从数据库查询用户信息
     * 
     * 注意: 显式添加租户条件，避免依赖TenantLineInnerInterceptor造成循环调用
     */
    private User getUserFromDatabase(String userId, String tenantId) {
        try {
            LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(User::getId, userId);
            
            // 显式添加租户条件，避免循环调用
            if (tenantId != null) {
                queryWrapper.eq(User::getTenantId, tenantId);
            }
            
            User user = userMapper.selectOne(queryWrapper);
            logger.debug("查询用户信息: userId={}, tenantId={}, found={}", userId, tenantId, user != null);
            return user;
            
        } catch (Exception e) {
            logger.error("查询用户信息失败: userId={}, tenantId={}, error={}", userId, tenantId, e.getMessage(), e);
            return null;
        }
    }
    
    // ==================== 权限版本号管理工具方法（未来扩展） ====================
    
    /**
     * 递增用户权限版本号
     * 
     * 用于在权限真正变化时主动更新版本号，使前端能够及时检测到权限变化
     * 
     * 应在以下场景调用：
     * 1. 用户角色分配/移除
     * 2. 用户所属角色的权限变更
     * 3. 用户直接权限分配
     * 4. 用户部门变更（影响数据权限）
     * 
     * @param userId 用户ID
     * @return 是否更新成功
     */
    public boolean incrementUserPermVersion(String userId) {
        try {
            long newVersion = System.currentTimeMillis();
            int updated = userMapper.updatePermVersionById(userId, newVersion);
            
            if (updated > 0) {
                logger.info("✅ 用户权限版本号已更新: userId={}, newVersion={}", userId, newVersion);
                return true;
            } else {
                logger.warn("⚠️ 更新用户权限版本号失败（用户不存在?）: userId={}", userId);
                return false;
            }
            
        } catch (Exception e) {
            logger.error("❌ 更新用户权限版本号异常: userId={}, error={}", userId, e.getMessage(), e);
            return false;
        }
    }
    
    /**
     * 批量递增用户权限版本号
     * 
     * 用于角色权限变更时，批量更新该角色下所有用户的版本号
     * 
     * @param userIds 用户ID列表
     * @return 成功更新的用户数量
     */
    public int batchIncrementUserPermVersion(List<String> userIds) {
        if (CollectionUtils.isEmpty(userIds)) {
            return 0;
        }
        
        try {
            long newVersion = System.currentTimeMillis();
            int updated = userMapper.batchUpdatePermVersion(userIds, newVersion);
            
            logger.info("批量更新用户权限版本号完成: total={}, success={}", userIds.size(), updated);
            return updated;
            
        } catch (Exception e) {
            logger.error("批量更新用户权限版本号异常: userCount={}, error={}", 
                userIds.size(), e.getMessage(), e);
            return 0;
        }
    }
}
